package cn.desk.commons.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class PropertyInjectionInvoker implements InjectionInvoker,
		ApplicationContextAware {
	protected static ApplicationContext context;
	private String propertyName;
	private String propertyValue;
	private String reference;
	private Object target;

	@Override
	public void invoke(Object target) {
		this.target = target;
		if (propertyName == null) {
			throw new RuntimeException();
		}
		if (propertyValue == null && reference == null) {
			throw new RuntimeException();
		}
		if (propertyValue != null) {
			writeValue(propertyValue);
		} else {
			Object ref = context.getBean(reference);
			writeValue(ref);
		}
	}

	private void writeValue(Object value) {
		Class<?> clazz = target.getClass();
		boolean hasMethod = true;
		try {
			// PropertyDescriptor pd = new PropertyDescriptor(propertyName,
			// clazz,
			// propertyName, getWriterMethodName(propertyName));
			// clazz.getMethod(getWriterMethodName(propertyName), Object.class);
			Method m[] = clazz.getMethods();
			String methodName = getWriterMethodName(propertyName);
			for (Method method : m) {
				if (method.getName().equals(methodName)) {
					hasMethod = false;
					try {
						method.invoke(target, value);
						return;
					} catch (InvocationTargetException e) {
					} catch (IllegalArgumentException e) {
						// e.printStackTrace();
					}
				}
			}
			if (hasMethod) {
				throw new NoSuchMethodError(methodName);
			}
			throw new IllegalArgumentException();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
	}

	private String getWriterMethodName(String propertyName) {
		StringBuilder sb = new StringBuilder("set");
		sb.append(propertyName.substring(0, 1).toUpperCase());
		sb.append(propertyName.substring(1));
		return sb.toString();
	}

	public String getPropertyName() {
		return propertyName;
	}

	public void setPropertyName(String propertyName) {
		this.propertyName = propertyName;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		context = applicationContext;
	}

	public String getReference() {
		return reference;
	}

	public void setReference(String reference) {
		this.reference = reference;
	}

	public String getPropertyValue() {
		return propertyValue;
	}

	public void setPropertyValue(String propertyValue) {
		this.propertyValue = propertyValue;
	}

	@Override
	public void prepareInvoke() {
		
	}

	@Override
	public void afterInvoke() {
		
	}
}
